package com.heima.admin.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.heima.apis.article.IArticleClient;
import com.heima.audit.aliyun.GreenImageScan;
import com.heima.audit.aliyun.GreenTextScan;
import com.heima.audit.tess4j.Tess4jClient;
import com.heima.common.constants.WemediaConstants;
import com.heima.common.redis.CacheService;
import com.heima.file.service.FileStorageService;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.pojos.WmChannel;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmSensitive;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.admin.mapper.WmSensitiveMapper;
import com.heima.admin.service.WmChannelService;
import com.heima.admin.service.WmNewsAutoScanService;
import com.heima.admin.service.WmNewsService;
import com.heima.admin.service.WmUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.util.*;
import java.util.stream.Collectors;

@Component
public class WmNewsAutoScanServiceImpl implements WmNewsAutoScanService {

    @Autowired
    private GreenTextScan greenTextScan;

    @Autowired
    private FileStorageService fileStorageService;

    @Autowired
    private GreenImageScan greenImageScan;

    @Autowired
    private IArticleClient articleClient;

    @Autowired
    private WmNewsService wmNewsService;

    @Autowired
    private WmUserService wmUserService;

    @Autowired
    private WmChannelService wmChannelService;

    @Autowired
    private WmSensitiveMapper wmSensitiveMapper;

    @Autowired
    Tess4jClient tess4jClient;


    @Autowired
    private CacheService cacheService;


    @Override
    @Async //异步处理
    public void autoScanWmNews(WmNews wmNews) {
         boolean contentAuditResult = true;
        Map<String, Object> wmNewsMap = parseWmNews(wmNews);
        String content = String.valueOf(wmNewsMap.get("content"));
        //boolean contentAuditResult = contentAudit(wmNews, content);
        if (contentAuditResult) {
            Set<String> imagesAudit = (Set<String>)wmNewsMap.get("images");
            //boolean imageAuditResult = imageAudit(wmNews, imagesAudit);
            boolean imageAuditResult = true;
            if (imageAuditResult) {
                //发起feign数据同步
                ArticleDto articleDto = new ArticleDto();
                BeanUtils.copyProperties(wmNews, articleDto);
                articleDto.setContent(wmNews.getContent());
                articleDto.setAuthorId(Long.valueOf(wmNews.getUserId()));
                articleDto.setLayout(Short.valueOf("" + wmNews.getType()));
                WmUser user = wmUserService.getById(wmNews.getUserId());
                articleDto.setAuthorName(user.getName());
                WmChannel channel = wmChannelService.getById(wmNews.getChannelId());
                articleDto.setChannelName(channel.getName());
                ResponseResult responseResult = articleClient.saveArticle(articleDto);
                if (responseResult.getCode() == AppHttpCodeEnum.SUCCESS.getCode()) {
                    Long articleId = Long.valueOf("" + responseResult.getData());
                    wmNews.setArticleId(articleId);
                    updateWmNews(wmNews, WmNews.Status.PUBLISHED, "发送成功");
                } else {
                    updateWmNews(wmNews, WmNews.Status.ADMIN_AUTH, "转人工");
                }
            }
        }
    }


    private Map<String, Object> parseWmNews(WmNews wmNews){
        StringBuffer contentBuffer =new StringBuffer(wmNews.getTitle()); //文章要审计的内容
        //提取文章素材
        Set<String> auditImages= new HashSet<>();
        JSONArray jsonArray = JSON.parseArray(wmNews.getContent());
        for (Object o : jsonArray) {
            JSONObject jsonObject = (JSONObject) o;
            if(jsonObject.get("type").equals("image")){
                auditImages.add(jsonObject.get("value").toString());
            }else{
                //文章内容
                contentBuffer.append(jsonObject.get("value").toString());
            }
        }
        if(StringUtils.isNotBlank(wmNews.getImages())){
            String[] images = wmNews.getImages().split(",");
            for (String image : images) {
                auditImages.add(image);
            }
        }
        Map<String,Object> map =new HashMap<>();
        map.put("content", contentBuffer.toString());
        map.put("images", auditImages);
        return  map;
    }

    private boolean dfaSensitives(WmNews wmNews,String content){
        //自定义敏感词过滤 dfa算法
        //先读取缓存，如果换成没有，再读取数据库，把数据库数据放入缓存
        Set<String> sensitivesSet = cacheService.setMembers(WemediaConstants.CACHE_KEY_SECSITIVE);
        //List<String> sensitivesList;
        if(sensitivesSet.isEmpty()){
            List<WmSensitive> wmSensitives = wmSensitiveMapper.selectList(null);
            List<String> sensitivesList = wmSensitives.stream().map(WmSensitive::getSensitives).collect(Collectors.toList());
            if(!sensitivesList.isEmpty()){
                for (String sensitive : sensitivesList) {
                    cacheService.sAdd(WemediaConstants.CACHE_KEY_SECSITIVE,sensitive);
                }
            }
            sensitivesSet = cacheService.setMembers(WemediaConstants.CACHE_KEY_SECSITIVE);
        }
        if(!sensitivesSet.isEmpty()){
            SensitiveWordUtil.initMap(sensitivesSet);
            Map<String, Integer> result = SensitiveWordUtil.matchWords(content);
            if(!result.isEmpty()){
                updateWmNews(wmNews, WmNews.Status.FAIL, "包含敏感词，审核失败");
                return false;
            }
        }
        return true;
    }

    private boolean contentAudit(WmNews wmNews,String content){
        try {
            //自定义敏感词过滤 dfa算法
            boolean sensitivesExit = dfaSensitives(wmNews, content);
            //fase 存在
            if(!sensitivesExit){
                return false;
            }
            Map greeTextScan = greenTextScan.greeTextScan(content);
            String suggestion =String.valueOf(greeTextScan.get("suggestion"));
            if(StringUtils.isNotBlank(suggestion)){
                //block 文字有敏感词
                if("block".equals(suggestion)){
                    updateWmNews(wmNews, WmNews.Status.FAIL, "包含敏感词，审核失败");
                    return false;
                }
                //review
                if("review".equals(suggestion)){
                    updateWmNews(wmNews, WmNews.Status.ADMIN_AUTH, "需要人工审核");
                    return false;
                }
            }

        } catch (Exception e) {
            // e.printStackTrace();
            return false;
        }

        return true;
    }

    private boolean imageAudit(WmNews wmNews, Set<String> imageList){
        try {
            if(!imageList.isEmpty()){
                List<byte []> list = new ArrayList<>();
                for (String url : imageList) {
                    byte[] bytes = fileStorageService.downLoadFile(url);
                    ByteArrayInputStream in = new ByteArrayInputStream(bytes);
                    BufferedImage imageFile = ImageIO.read(in);
                    String result = tess4jClient.doOCR(imageFile);
                    boolean sensitivesNotExit = dfaSensitives(wmNews, result);
                    //fasle 检验出来
                    if(!sensitivesNotExit){
                        return false;
                    }
                    list.add(bytes);
                }

                Map greeTextScan = greenImageScan.imageScan(list);
                String suggestion =String.valueOf(greeTextScan.get("suggestion"));
                if(StringUtils.isNotBlank(suggestion)){
                    //block 文字有敏感词
                    if("block".equals(suggestion)){
                        updateWmNews(wmNews, WmNews.Status.FAIL, "图片审核失败");
                        return false;
                    }
                    //review
                    if("review".equals(suggestion)){
                        updateWmNews(wmNews, WmNews.Status.ADMIN_AUTH, "需要人工审核");
                        return false;
                    }
                }
            }
        } catch (Exception e) {
            // e.printStackTrace();
            return false;
        }

        return true;
    }

    private void updateWmNews(WmNews wmNews, WmNews.Status fail, String s) {
        wmNews.setStatus(fail.getCode());
        wmNews.setReason(s);
        wmNewsService.updateById(wmNews);
    }


}
